return rc;
}
+/* value: 0 - disable sched_smt_power_savings
+ 1 - enable sched_smt_power_savings
+ */
+int xc_set_sched_opt_smt(int xc_handle, uint32_t value)
+{
+ int rc;
+ DECLARE_SYSCTL;
+
+ sysctl.cmd = XEN_SYSCTL_pm_op;
+ sysctl.u.pm_op.cmd = XEN_SYSCTL_pm_op_set_sched_opt_smt;
+ sysctl.u.pm_op.cpuid = 0;
+ sysctl.u.pm_op.set_sched_opt_smt = value;
+ rc = do_sysctl(xc_handle, &sysctl);
+
+ return rc;
+}
+
int xc_get_cputopo(int xc_handle, struct xc_get_cputopo *info);
+int xc_set_sched_opt_smt(int xc_handle, uint32_t value);
+
#endif /* XENCTRL_H */
" set-up-threshold [cpuid] <num> set up threshold on CPU <cpuid> or all\n"
" it is used in ondemand governor.\n"
" get-cpu-topology get thread/core/socket topology info\n"
+ " set-sched-smt enable|disable enable/disable scheduler smt power saving\n"
" start [seconds] start collect Cx/Px statistics,\n"
" output after CTRL-C or SIGINT or several seconds.\n"
);
return ;
}
+void set_sched_smt_func(int argc, char *argv[])
+{
+ int value, rc;
+
+ if (argc != 1){
+ show_help();
+ exit(-1);
+ }
+
+ if ( !strncmp(argv[0], "disable", sizeof("disable")) )
+ {
+ value = 0;
+ }
+ else if ( !strncmp(argv[0], "enable", sizeof("enable")) )
+ {
+ value = 1;
+ }
+ else
+ {
+ show_help();
+ exit(-1);
+ }
+
+ rc = xc_set_sched_opt_smt(xc_fd, value);
+ printf("%s sched_smt_power_savings %s\n", argv[0],
+ rc? "failed":"successeed" );
+
+ return;
+}
+
struct {
const char *name;
void (*function)(int argc, char *argv[]);
{ "set-sampling-rate", scaling_sampling_rate_func },
{ "set-up-threshold", scaling_up_threshold_func },
{ "get-cpu-topology", cpu_topology_func},
+ { "set-sched-smt", set_sched_smt_func},
};
int main(int argc, char *argv[])
{
cpumask_t cpu_idlers;
cpumask_t nxt_idlers;
- int nxt;
+ int nxt, weight_cpu, weight_nxt;
nxt = cycle_cpu(cpu, cpus);
cpus_and(nxt_idlers, idlers, cpu_core_map[nxt]);
}
- if ( cpus_weight(cpu_idlers) < cpus_weight(nxt_idlers) )
+ weight_cpu = cpus_weight(cpu_idlers);
+ weight_nxt = cpus_weight(nxt_idlers);
+ if ( ( (weight_cpu < weight_nxt) ^ sched_smt_power_savings )
+ && (weight_cpu != weight_nxt) )
{
cpu = nxt;
cpu_clear(cpu, cpus);
static char opt_sched[10] = "credit";
string_param("sched", opt_sched);
+/* if sched_smt_power_savings is set,
+ * scheduler will give preferrence to partially idle package compared to
+ * the full idle package, when picking pCPU to schedule vCPU.
+ */
+int sched_smt_power_savings = 0;
+boolean_param("sched_smt_power_savings", sched_smt_power_savings);
+
#define TIME_SLOP (s32)MICROSECS(50) /* allow time to slip a bit */
/* Various timer handlers. */
printk("Scheduler: %s (%s)\n", ops.name, ops.opt_name);
SCHED_OP(dump_settings);
+ printk("sched_smt_power_savings: %s\n",
+ sched_smt_power_savings? "enabled":"disabled");
printk("NOW=0x%08X%08X\n", (u32)(now>>32), (u32)now);
for_each_online_cpu ( i )
break;
}
+ case XEN_SYSCTL_pm_op_set_sched_opt_smt:
+ {
+ uint32_t saved_value;
+
+ saved_value = sched_smt_power_savings;
+ sched_smt_power_savings = !!op->set_sched_opt_smt;
+ op->set_sched_opt_smt = saved_value;
+
+ break;
+ }
+
default:
printk("not defined sub-hypercall @ do_pm_op\n");
ret = -ENOSYS;
uint32_t ctrl_type;
uint32_t ctrl_value;
-}
-;
-/* Get physical CPU topology information. */
-
+};
+/* Get physical CPU topology information. */
#define INVALID_TOPOLOGY_ID (~0U)
struct xen_get_cputopo {
/* IN: maximum addressable entry in
/* get CPU topology */
#define XEN_SYSCTL_pm_op_get_cputopo 0x20
+ /* set/reset scheduler power saving option */
+ #define XEN_SYSCTL_pm_op_set_sched_opt_smt 0x21
+
uint32_t cmd;
uint32_t cpuid;
union {
struct xen_set_cpufreq_para set_para;
uint64_t get_avgfreq;
struct xen_get_cputopo get_topo;
+ uint32_t set_sched_opt_smt;
};
};
#define is_hvm_vcpu(v) (is_hvm_domain(v->domain))
#define need_iommu(d) ((d)->need_iommu && !(d)->is_hvm)
+extern int sched_smt_power_savings;
+
extern enum cpufreq_controller {
FREQCTL_none, FREQCTL_dom0_kernel, FREQCTL_xen
} cpufreq_controller;